home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / misc / 40 / tty.c < prev    next >
C/C++ Source or Header  |  1986-07-17  |  7KB  |  339 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* tty.c - version 1.0.3 */
  3. /* With thanks to the people who sent code for SYSV - hpscdi!jon,
  4.    arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
  5.  
  6. #include <stdio.h>
  7. #include "hack.h"
  8.  
  9. #ifndef MSDOS
  10. #define MSDOS
  11. #endif
  12. #ifdef MSDOS
  13. static char erase_char, kill_char;
  14. static boolean settty_needed = FALSE;
  15. #else MSDOS
  16. /*
  17.  * The distinctions here are not BSD - rest but rather USG - rest, as
  18.  * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
  19.  */
  20. #ifdef BSD
  21. #define    V7
  22. #else
  23. #define USG
  24. #endif BSD
  25.  
  26. /*
  27.  * Some systems may have getchar() return EOF for various reasons, and
  28.  * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
  29.  */
  30. #ifndef BSD
  31. #define    NR_OF_EOFS    20
  32. #endif BSD
  33.  
  34.  
  35. #ifdef USG
  36.  
  37. #include    <termio.h>
  38. #define termstruct    termio
  39. #define kill_sym    c_cc[VKILL]
  40. #define erase_sym    c_cc[VERASE]
  41. #define EXTABS        TAB3
  42. #define tabflgs        c_oflag
  43. #define echoflgs    c_lflag
  44. #define cbrkflgs    c_lflag
  45. #define CBRKMASK    ICANON
  46. #define CBRKON        ! /* reverse condition */
  47. #define OSPEED(x)    ((x).c_cflag & CBAUD)
  48. #define GTTY(x)        (ioctl(0, TCGETA, x))
  49. #define STTY(x)        (ioctl(0, TCSETA, x))    /* TCSETAF? TCSETAW? */
  50.  
  51. #else    /* V7 */
  52.  
  53. #include    <sgtty.h>
  54. #define termstruct    sgttyb
  55. #define    kill_sym    sg_kill
  56. #define    erase_sym    sg_erase
  57. #define EXTABS        XTABS
  58. #define tabflgs        sg_flags
  59. #define echoflgs    sg_flags
  60. #define cbrkflgs    sg_flags
  61. #define CBRKMASK    CBREAK
  62. #define CBRKON        /* empty */
  63. #define OSPEED(x)    (x).sg_ospeed
  64. #define GTTY(x)        (gtty(0, x))
  65. #define STTY(x)        (stty(0, x))
  66.  
  67. #endif USG
  68.  
  69. extern short ospeed;
  70. static char erase_char, kill_char;
  71. static boolean settty_needed = FALSE;
  72. struct termstruct inittyb, curttyb;
  73. #endif MSDOS
  74.  
  75. /*
  76.  * Get initial state of terminal, set ospeed (for termcap routines)
  77.  * and switch off tab expansion if necessary.
  78.  * Called by startup() in termcap.c and after returning from ! or ^Z
  79.  */
  80. gettty(){
  81. #ifdef MSDOS
  82.     erase_char = '\b';
  83.     kill_char = 21;        /* cntl-U */
  84. #else
  85.     if(GTTY(&inittyb) < 0)
  86.         perror("Hack (gettty)");
  87.     curttyb = inittyb;
  88.     ospeed = OSPEED(inittyb);
  89.     erase_char = inittyb.erase_sym;
  90.     kill_char = inittyb.kill_sym;
  91.     getioctls();
  92.  
  93.     /* do not expand tabs - they might be needed inside a cm sequence */
  94.     if(curttyb.tabflgs & EXTABS) {
  95.         curttyb.tabflgs &= ~EXTABS;
  96.         setctty();
  97.     }
  98. #endif MSDOS
  99.     settty_needed = TRUE;
  100. }
  101.  
  102. /* reset terminal to original state */
  103. settty(s) char *s; {
  104.     end_screen();
  105.     clear_screen();
  106.     if(s) printf(s);
  107.     (void) fflush(stdout);
  108. #ifdef    MSDOS
  109.     flags.echo = ON;
  110.     flags.cbreak = OFF;
  111. #else
  112.     if(STTY(&inittyb) < 0)
  113.         perror("Hack (settty)");
  114.     flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
  115.     flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
  116.     setioctls();
  117. #endif MSDOS
  118. }
  119.  
  120. setctty(){
  121. #ifndef MSDOS
  122.     if(STTY(&curttyb) < 0)
  123.         perror("Hack (setctty)");
  124. #endif MSDOS
  125. }
  126.  
  127.  
  128. setftty(){
  129. #ifdef MSDOS
  130.     flags.cbreak = ON;
  131.     flags.echo = OFF;
  132. #else
  133. register int ef = 0;            /* desired value of flags & ECHO */
  134. register int cf = CBRKON(CBRKMASK);    /* desired value of flags & CBREAK */
  135. register int change = 0;
  136.     flags.cbreak = ON;
  137.     flags.echo = OFF;
  138.     /* Should use (ECHO|CRMOD) here instead of ECHO */
  139.     if((curttyb.echoflgs & ECHO) != ef){
  140.         curttyb.echoflgs &= ~ECHO;
  141. /*        curttyb.echoflgs |= ef;                    */
  142.         change++;
  143.     }
  144.     if((curttyb.cbrkflgs & CBRKMASK) != cf){
  145.         curttyb.cbrkflgs &= ~CBRKMASK;
  146.         curttyb.cbrkflgs |= cf;
  147. #ifdef USG
  148.         /* be satisfied with one character; no timeout */
  149.         curttyb.c_cc[VMIN] = 1;        /* was VEOF */
  150.         curttyb.c_cc[VTIME] = 0;    /* was VEOL */
  151. #endif USG
  152.         change++;
  153.     }
  154.     if(change){
  155.         setctty();
  156.     }
  157. #endif MSDOS
  158.     start_screen();
  159. }
  160.  
  161.  
  162. /* fatal error */
  163. /*VARARGS1*/
  164. error(s,x,y) char *s; {
  165.     if(settty_needed)
  166.         settty((char *) 0);
  167.     printf(s,x,y);
  168.     putchar('\n');
  169.     exit(1);
  170. }
  171.  
  172. /*
  173.  * Read a line closed with '\n' into the array char bufp[BUFSZ].
  174.  * (The '\n' is not stored. The string is closed with a '\0'.)
  175.  * Reading can be interrupted by an escape ('\033') - now the
  176.  * resulting string is "\033".
  177.  */
  178. getlin(bufp)
  179. register char *bufp;
  180. {
  181.     register char *obufp = bufp;
  182.     register int c;
  183.  
  184.     flags.toplin = 2;        /* nonempty, no --More-- required */
  185.     for(;;) {
  186.         (void) fflush(stdout);
  187.         if((c = getchar()) == EOF) {
  188.             *bufp = 0;
  189.             return;
  190.         }
  191.         if(c == '\033') {
  192.             *obufp = c;
  193.             obufp[1] = 0;
  194.             return;
  195.         }
  196.         if(c == erase_char || c == '\b') {
  197.             if(bufp != obufp) {
  198.                 bufp--;
  199.                 putstr("\b \b"); /* putsym converts \b */
  200.             } else    bell();
  201.         } else if(c == '\n') {
  202.             *bufp = 0;
  203.             return;
  204.         } else if(' ' <= c && c < '\177') {
  205.                 /* avoid isprint() - some people don't have it
  206.                    ' ' is not always a printing char */
  207.             *bufp = c;
  208.             bufp[1] = 0;
  209.             putstr(bufp);
  210.             if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  211.                 bufp++;
  212.         } else if(c == kill_char || c == '\177') { /* Robert Viduya */
  213.                 /* this test last - @ might be the kill_char */
  214.             while(bufp != obufp) {
  215.                 bufp--;
  216.                 putstr("\b \b");
  217.             }
  218.         } else
  219.             bell();
  220.     }
  221. }
  222.  
  223. getret() {
  224.     cgetret("");
  225. }
  226.  
  227. cgetret(s)
  228. register char *s;
  229. {
  230.     putsym('\n');
  231.     if(flags.standout)
  232.         standoutbeg();
  233.     putstr("Hit ");
  234.     putstr(flags.cbreak ? "space" : "return");
  235.     putstr(" to continue: ");
  236.     if(flags.standout)
  237.         standoutend();
  238.     xwaitforspace(s);
  239. }
  240.  
  241. char morc;    /* tell the outside world what char he used */
  242.  
  243. xwaitforspace(s)
  244. register char *s;    /* chars allowed besides space or return */
  245. {
  246. register int c;
  247.  
  248.     morc = 0;
  249.     while((c = readchar()) != '\n') {
  250.         if(flags.cbreak) {
  251.         if(c == ' ') break;
  252.         if(s && index(s,c)) {
  253.             morc = c;
  254.             break;
  255.         }
  256.         bell();
  257.         }
  258.     }
  259. }
  260.  
  261. char *
  262. parse()
  263. {
  264.     static char inline[COLNO];
  265.     register foo;
  266.  
  267.     flags.move = 1;
  268.     if(!Invisible) curs_on_u(); else home();
  269. #ifdef DGK
  270.     /* provide feedback when the multi count gets large -dgk */
  271.     while((foo = readchar()) >= '0' && foo <= '9') {
  272.         multi = 10*multi+foo-'0';
  273.         if (multi >= 10) {
  274.             remember_topl();
  275.             home();
  276.             cl_end();
  277.             printf("count: %d", multi);
  278.         }
  279.     }
  280. #else
  281.     while((foo = readchar()) >= '0' && foo <= '9')
  282.         multi = 10*multi+foo-'0';
  283. #endif DGK
  284.     if(multi) {
  285.         multi--;
  286.         save_cm = inline;
  287.     }
  288.     inline[0] = foo;
  289.     inline[1] = 0;
  290.     if(foo == 'f' || foo == 'F'){
  291.         inline[1] = getchar();
  292. #ifdef QUEST
  293.         if(inline[1] == foo) inline[2] = getchar(); else
  294. #endif QUEST
  295.         inline[2] = 0;
  296.     }
  297.     if(foo == 'm' || foo == 'M'){
  298.         inline[1] = getchar();
  299.         inline[2] = 0;
  300.     }
  301.     clrlin();
  302.     return(inline);
  303. }
  304.  
  305. char
  306. readchar() {
  307.     register int sym;
  308.  
  309.     (void) fflush(stdout);
  310.     if((sym = getchar()) == EOF)
  311. #ifdef NR_OF_EOFS
  312.     { /*
  313.        * Some SYSV systems seem to return EOFs for various reasons
  314.        * (?like when one hits break or for interrupted systemcalls?),
  315.        * and we must see several before we quit.
  316.        */
  317.         register int cnt = NR_OF_EOFS;
  318.         while (cnt--) {
  319.             clearerr(stdin);    /* omit if clearerr is undefined */
  320.             if((sym = getchar()) != EOF) goto noteof;
  321.         }
  322.         end_of_input();
  323.          noteof:    ;
  324.     }
  325. #else
  326.         end_of_input();
  327. #endif NR_OF_EOFS
  328.     if(flags.toplin == 1)
  329.         flags.toplin = 2;
  330.     return((char) sym);
  331. }
  332.  
  333. end_of_input()
  334. {
  335.     settty("End of input?\n");
  336.     clearlocks();
  337.     exit(0);
  338. }
  339.